/**
 * Copyright &copy; 2016-2017 <a href="http://git.oschina.net/whoamien/backend_management">Backend Management</a> All rights reserved.
 */
package com.xw.framework.encryption;

import java.io.InputStream;
import java.security.interfaces.RSAPublicKey;
import java.text.MessageFormat;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.xw.util.ConvertUtils;
import com.xw.util.FileUtil;
import com.xw.util.RSAUtils;

/**
 * The Class EncryptionController.
 *
 * @author Xi Wei
 */
@Controller
@RequestMapping("/encryption")
@SessionAttributes("keys")
public class EncryptionController {

	/**
	 * Generate keypair.
	 *
	 * @param generateKeypair the generate keypair
	 * @param session the session
	 * @return the public key impl
	 */
	@RequestMapping("/generateKeypair")
	public @ResponseBody
	PublicKeyImpl generateKeypair(
			@RequestParam(required = false) Boolean generateKeypair,
			HttpSession session) {

		PublicKeyImpl retVal = null;

		if (generateKeypair != null && generateKeypair == true) {

			InputStream is = getClass().getResourceAsStream("/rsa_1024_pub.pem");
			String publicKeyString = ConvertUtils.txt2String(is);
			RSAPublicKey publicKey = (RSAPublicKey)RSAUtils.getPublicKey(publicKeyString);
		
			retVal = new PublicKeyImpl();
			retVal.setE(publicKey.getPublicExponent().toString(16));
			retVal.setN(publicKey.getModulus().toString(16));
			retVal.setMaxdigits(String.valueOf(RSAUtils.getMaxDigits(512)));

		}
		return retVal;
	}
	
	/**
	 * Gets the public key.
	 *
	 * @param generateKeypair the generate keypair
	 * @param request the request
	 * @return the public key
	 */
	@RequestMapping("/getPublicKey")
	public @ResponseBody
	PublicKey getPublicKey(
			@RequestParam(required = false) Boolean generateKeypair,
			HttpServletRequest request) {

		PublicKey retVal = null;
		if (generateKeypair != null && generateKeypair == true) {
			InputStream is = getClass().getResourceAsStream("/rsa_1024_pub.pem");
			String publicKey = ConvertUtils.txt2String(is);
			
			retVal = new PublicKey();
			retVal.setPublickey(publicKey);
		}
		return retVal;
	}
	
	/**
	 * Handshake.
	 *
	 * @param key the key
	 * @param session the session
	 * @return the handshake
	 */
	@RequestMapping("/handshake")
	@ResponseBody
	public Handshake handshake(String key,HttpSession session){

		String privateString = ConvertUtils.txt2String(getClass().getResourceAsStream("/rsa_1024_priv.pem"));
		
		System.out.println("The key to handshake is " + key);
		String decrypted = RSAUtils.decodeSecret(privateString, key);
		
		session.removeAttribute("keys");
		session.setAttribute("jCryptionKey", decrypted);
		System.out.println("The key to handshake is " + key);
		System.out.println("The key after decrypted is " + decrypted);
		
		String ct = AESUtil.encrypt(decrypted,decrypted);
		System.out.println("The key after AES encrypt to handshake is " + ct);
		Handshake handshake = new Handshake();
		handshake.setChallenge(ct);
		return handshake;
	}
	
	/**
	 * The Class Handshake.
	 *
	 * @author Xi Wei
	 */
	class Handshake{
		private String challenge;

		/**
		 * Gets the challenge.
		 *
		 * @return the challenge
		 */
		public String getChallenge() {
			return challenge;
		}

		/**
		 * Sets the challenge.
		 *
		 * @param challenge the new challenge
		 */
		public void setChallenge(String challenge) {
			this.challenge = challenge;
		}
		
	}
	
	/**
	 * Encrypt data.
	 *
	 * @param password the password
	 * @param session the session
	 * @return the string
	 */
	@RequestMapping("/encryptData")
	@ResponseBody
	public String encryptData(String password,HttpSession session){
		
		String key = (String)session.getAttribute("jCryptionKey");
		String ct = AESUtil.encrypt(password,key);
		return "{"+MessageFormat.format("\"data\":\"{0}\"", ct) + "}";
		
	}
	
	/**
	 * Decrypt data.
	 *
	 * @param decrypt the decrypt
	 * @param session the session
	 * @return the string
	 */
	@RequestMapping("/decryptData")
	@ResponseBody
	public String decryptData(String decrypt,HttpSession session){
		
		String privateString = ConvertUtils.txt2String(getClass().getResourceAsStream("/rsa_1024_priv.pem"));
		String ct = RSAUtils.decodeSecret(privateString, decrypt);
		String key = (String)session.getAttribute("jCryptionKey");
		
		
		System.out.println("Encrypted :" + decrypt);;
		
		System.out.println("Decrypted:" + ct);;
		return "{"+MessageFormat.format("\"data\":\"{0}\"", ct) + "}";		
	}
	
	/**
	 * Encrypt AES data.
	 *
	 * @param plain the plain
	 * @param key the key
	 * @return the string
	 */
	@RequestMapping("/encryptAESData")
	@ResponseBody
	public String encryptAESData(String plain,String key){
		return AESUtil.encrypt(key, plain);
	}
	
	/**
	 * Decrypt AES data.
	 *
	 * @param encrypted the encrypted
	 * @param key the key
	 * @return the string
	 */
	@RequestMapping("/decryptAESData")
	@ResponseBody
	public String decryptAESData(String encrypted,String key){
		return AESUtil.decryptForJS(key, encrypted);
	}
}
